package luke4fun.wheresmymoney.panel;

import android.R;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.RelativeLayout.LayoutParams;

import java.util.ArrayList;
import java.util.List;

public class TrendChartPanel extends View {

	private List<Long> dataList;
    private final int PADDING = 20;
    private final int DEFAULT_WIDTH = 620;
    private final int DEFAULT_HEIGHT = 320;
    private float leftTopX = 20f;
    private float leftTopY = 20f;
    private float rightBottomX = DEFAULT_WIDTH - PADDING;
    private float rightBottomY = DEFAULT_HEIGHT - PADDING;

    private Canvas canvas;
    private Paint paint = new Paint();
    private float startX = leftTopX;
    private float startY = rightBottomY;
    private List<Path> pathList = new ArrayList<Path>();

    private ObjectAnimator ani;
    private int aniIndex = 0;
    private boolean isFirst = true;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            aniIndex = message.what;
            postInvalidate();
        }
    };

	public void setDataList (List<Long> dataList) {
		this.dataList = dataList;
	}

	public TrendChartPanel(Context context) {
		super(context);
	}

	public TrendChartPanel (Context context, AttributeSet attrs) {
		super(context, attrs);
	}

    @Override
	protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
		int width = DEFAULT_WIDTH;
	    if (getLayoutParams().width == LayoutParams.WRAP_CONTENT)
	    {
	    }
	    else if ((getLayoutParams().width == LayoutParams.MATCH_PARENT))
	    {
	        width = MeasureSpec.getSize(widthMeasureSpec);
	    }
	    else {
	        width = getLayoutParams().width;
        }


	    int height = DEFAULT_HEIGHT;
	    if (getLayoutParams().height == LayoutParams.WRAP_CONTENT)
	    {
	    }
	    else if ((getLayoutParams().height == LayoutParams.MATCH_PARENT))
	    {
	        height = MeasureSpec.getSize(heightMeasureSpec);
	    }
	    else {
	        height = getLayoutParams().height;
        }

        rightBottomX = width  - PADDING;
        rightBottomY = height - PADDING;
	    setMeasuredDimension(width|MeasureSpec.EXACTLY, height|MeasureSpec.EXACTLY);
        if (isFirst) {
            setUpAnimationPath();
            startDrawPath();
            isFirst = false;
        }
	}

	@Override
    public void onDraw(Canvas canvas) {
		super.onDraw(canvas);
        // draw stroke
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        paint.setColor(getResources().getColor(R.color.holo_orange_light));
        paint.setAntiAlias(true);
        paint.setPathEffect(new CornerPathEffect(3));
        this.canvas = canvas;

        Path path = new Path();
        for (Path p : pathList) {
            path.addPath(p);
        }
        canvas.drawPath(path, paint);
    }

    public void setUpAnimationPath() {

        if (dataList != null && dataList.size() > 0) {
            float xPoints = (rightBottomX - leftTopX) / dataList.size();
            long max = 0;

            for (Long price : dataList) {
                max = price > max ? price : max;
            }

            float xCord = leftTopX;
            float yCord = rightBottomY;

            List<PathPoint> pathPointList = new ArrayList<PathPoint>();
            pathPointList.add(new PathPoint(PathPoint.MOVE, xCord, yCord));
            for (Long price : dataList) {
                xCord += xPoints;
                yCord = rightBottomY - ((rightBottomY - leftTopY) * price / max);
                pathPointList.add(new PathPoint(PathPoint.LINE, xCord, yCord));
            }

            ani = ObjectAnimator.ofObject(this, "linePath", new PathEvaluator(), pathPointList.toArray());
            ani.setDuration(3000);
            ani.setInterpolator(new LinearInterpolator());
        }
    }

    public void startDrawPath() {
        if (ani != null) {
            ani.start();
        }
    }

    public void setLinePath(PathPoint point) {
    }

    private class PathPoint {

        public static final int MOVE = 0;
        public static final int LINE = 1;

        private int operation;
        private float pointX;
        private float pointY;

        private int getOperation() {
            return operation;
        }

        public PathPoint(int operation, float x, float y) {
            this.operation = operation;
            this.pointX = x;
            this.pointY = y;
        }

        public PathPoint moveTo(float x, float y) {
            return new PathPoint(MOVE, x, y);
        }

        public PathPoint lineTo(float x, float y) {
            return new PathPoint(LINE, x, y);
        }
    }

    private class PathEvaluator implements TypeEvaluator<PathPoint> {

        @Override
        public PathPoint evaluate(float t, PathPoint startValue, PathPoint endValue) {
            Path path = new Path();
            float x, y;
            path.moveTo(startX, startY);
            if (endValue.getOperation() == PathPoint.LINE) {
                x = startValue.pointX + t * (endValue.pointX - startValue.pointX);
                y = startValue.pointY + t * (endValue.pointY - startValue.pointY);
                path.lineTo(x, y);
            } else {
                x = endValue.pointX;
                y = endValue.pointY;
                path.moveTo(x, y);
            }
            path.close();
            pathList.add(path);

            startX = x;
            startY = y;

            Message m = Message.obtain();
            m.what = pathList.size() -1 ;
            mHandler.sendMessage(m);
            return new PathPoint(PathPoint.MOVE, x, y);
        }
    }
}
